#include "bsp_config.h"

MQTT_CREATED_ENUM_Typedef mqtt_is_create = MQTT_NO_CREATED;  //指示当前MQTT是否已经创建
MQTT_STATE_ENUM_Typedef mqtt_is_connected = MQTT_DISCONNECT; //指示当前MQTT是否已连接
char mqtt_rev_buffer[1024];                                  //存放接受到的MQTT数据

WIFI_STATE_ENUM_Typedef current_wifi_state = WIFI_DISABLE; //默认当前wifi功能未开启
/*********************************************************************************************************************/
//下面是MQTT连接部分
/**
 *  @brief 这个函数是干嘛的!!
 *  @param 
 *  @brief 无  
 */
static void log_error_if_nonzero(const char *message, int error_code)
{
    if (error_code != 0)
    {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

/**
 *  @brief MQTT事件处理回调函数   重点对这个函数进行处理
 *  @param  event :MQTT事件 
 *  @brief  ESP_OK:表示成功  
 *          ESP_FAIL:表示失败 
 */
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    // your_context_t *context = event->context;
    switch (event->event_id)
    {
    case MQTT_EVENT_CONNECTED: //当MQTT连接上后
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        // msg_id = esp_mqtt_client_publish(client, "VPA0B0C0D0E0F0", "fuck_you", 0, 2, 0);
        // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        msg_id = esp_mqtt_client_subscribe(client, ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic, 2);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        mqtt_is_connected = MQTT_CONNECTED; //MQTT连接上了
        current_wifi_state = WIFI_CONED;    //wifi已经连上了(MQTT连上了,wifi就一定连上了)
        break;
    case MQTT_EVENT_DISCONNECTED: //MQTT自动重连已经开启
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        mqtt_is_connected = MQTT_DISCONNECT; //MQTT连接断了
        break;

    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        // msg_id = esp_mqtt_client_publish(client, "VPA0B0C0D0E0F0", "data", 0, 0, 0);
        // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        sprintf(mqtt_rev_buffer, "%s", event->data);
        if (mqtt_rev_sem)
        {
            xSemaphoreGive(mqtt_rev_sem); //通知MQTT接受线程,表示有新的消息来了
        }
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
        {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
    return ESP_OK;
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    mqtt_event_handler_cb(event_data);
}

esp_mqtt_client_handle_t mqtt_client = NULL;

static void mqtt_config(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .uri = "mqtt://47.100.126.119:1883",
        .client_id = ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic,
        .disable_auto_reconnect = false,
        .lwt_qos = 2,
        .lwt_retain = 0,
    }; //这里是MQTT的配置部分

    mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, mqtt_client);
    esp_mqtt_client_start(mqtt_client);
    mqtt_is_create = MQTT_IS_CREATED; //MQTT已经创建了
}

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t s_wifi_event_group; //和message是不同的

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;

static int s_retry_num = 0;

TaskHandle_t smartconfigTaskHandler = NULL;

/**
 *  @brief 配网线程
 *  @param param :void 类型的指针
 *  @brief 无  
 */
void smartconfig_task(void *parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_V2));
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));
    while (1)
    {
        current_wifi_state = WIFI_SMARTCONFIG; //wifi配网中
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if (uxBits & CONNECTED_BIT)
        {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if (uxBits & ESPTOUCH_DONE_BIT)
        {
            ESP_LOGI(TAG, "smartconfig over"); //wifi连上之后才关闭smartconfig
            esp_smartconfig_stop();
            vTaskDelete(NULL);
        }
    }
}

static void event_handler(void *arg, esp_event_base_t event_base,
                          int32_t event_id, void *event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    { //首先一上电先进行WIFI连接
        if (ConfigParam.MQTT_Param.mqtt_param_data.wifi_mode == WIFI_SCANNING)
        { //如果处于配网模式,就创建配网线程
            xTaskCreate(smartconfig_task, "smartconfig_task", 5120, NULL, 3,&smartconfigTaskHandler);
        }
        else if (ConfigParam.MQTT_Param.mqtt_param_data.wifi_mode == WIFI_CONNECT)
        {                                       //如果处于连接WIFI模式,就直接连接WIFI
            current_wifi_state = WIFI_CONN_ING; //wifi连接中
            esp_wifi_connect();                 //
        }
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT); //当没联上时,将连接标志位清除
        //当WIFI断开后
        mqtt_is_connected = MQTT_DISCONNECT; //MQTT没有连接上了(WIFI断了自然MQTT就会断开)
        // if (s_retry_num < ConfigParam.MQTT_Param.mqtt_param_data.wifi_maximum_retry)
        // {                                       //
            current_wifi_state = WIFI_CONN_ING; //wifi连接中
            esp_wifi_connect();
            // s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        // }
        // else                                      //wifi重连超过一定次数
        // {                                         //这里不改变存储在flash中的wifi连接状态
        //     s_retry_num = 0;                      //清零,否则下次就不会连10次了
        //     current_wifi_state = WIFI_PREDISABLE; //准备关闭wifi
        //     // wifi_smartconfig();                   //超过连接次数,进入配网模式
        //     MosOpenBLE();
        // }
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        s_retry_num = 0; //就是说连上WIFI后再断开重连,会重连10次
        current_wifi_state = WIFI_CONED; //wifi已经连上了
        ConfigParam.MQTT_Param.mqtt_param_data.wifi_mode = WIFI_CONNECT;
        write_config_param(&ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, ConfigParam.MQTT_Param.pC, ConfigParam.MQTT_Param.length);
        
        get_time(1);
        ESP_LOGI(TAG, "GOT IP");
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
        if (mqtt_is_create == MQTT_NO_CREATED)
        {                  //当发现MQTT client被销毁后,就得重新创建MQTT client
            mqtt_config(); //连上WIFI后开始连接MQTT
        }

    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE)
    {
        ESP_LOGI(TAG, "Scan done");
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL)
    {
        ESP_LOGI(TAG, "Found channel");
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
    {
        ESP_LOGI(TAG, "Got SSID and password"); //这里是配网完成后,进行wifi连接

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        /****************************************************************************************************************************/
        wifi_config_t wifi_config = {
            //关键词  wifi_config_t
            .sta.pmf_cfg.capable = true,
            .sta.pmf_cfg.required = false,
            .sta.threshold.authmode = WIFI_AUTH_WPA2_PSK,
            .sta.listen_interval = 3,
        };
        uint8_t rvd_data[33] = {0};

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid)); //将手机发过来的WIFI密码和WIFI名称复制过来
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true)
        {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }
        /****************************************************************************************************************************/

        /****************************************************************************************************************************/
        //写之前,将内存清空   还是清空内存比较合理一些
        memset(ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, 0, sizeof(ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid));
        memcpy(ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, evt->ssid, sizeof(ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid));

        memset(ConfigParam.MQTT_Param.mqtt_param_data.wifi_password, 0, sizeof(ConfigParam.MQTT_Param.mqtt_param_data.wifi_password));
        memcpy(ConfigParam.MQTT_Param.mqtt_param_data.wifi_password, evt->password, sizeof(ConfigParam.MQTT_Param.mqtt_param_data.wifi_password));

        ESP_LOGI(TAG, "PASSWORD:%s", ConfigParam.MQTT_Param.mqtt_param_data.wifi_password);
        ESP_LOGI(TAG, "WIFI_SSID:%s", ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid);
        if (evt->type == SC_TYPE_ESPTOUCH_V2)
        {
            ESP_ERROR_CHECK(esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)));
            ESP_LOGI(TAG, "RVD_DATA:");
            printf("%s", (void *)rvd_data); //这里是将WIFI连接相关的参数存起来
            printf("\n");
        }
        memset(ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic, 0, sizeof(ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic));
        memcpy(ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic, (char *)(&rvd_data), sizeof(ConfigParam.MQTT_Param.mqtt_param_data.mqtt_topic));
        write_config_param(&ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, ConfigParam.MQTT_Param.pC, ConfigParam.MQTT_Param.length);
        /****************************************************************************************************************************/

        ESP_ERROR_CHECK(esp_wifi_disconnect());
        ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); //
        esp_wifi_connect();                                              //配网后就是直接连接
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
    {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}

static esp_netif_t *sta_netif = NULL;

/**
 *  @brief wifi关闭函数
 *  @param 无
 *  @brief 无  
 */
void wifi_destroy(void)
{
    esp_wifi_stop();
}

/**
 *  @brief wifi开启函数
 *  @param 无
 *  @brief 无  
 */
void wifi_activate(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));

    wifi_config_t wifi_config = {
        //主要是当上电就连接wifi的情况
        .sta.pmf_cfg.capable = true,
        .sta.pmf_cfg.required = false,
        .sta.threshold.authmode = WIFI_AUTH_WPA2_PSK,
        .sta.listen_interval = 3,
    };
    memcpy(wifi_config.sta.ssid, ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, sizeof(wifi_config.sta.ssid));
    memcpy(wifi_config.sta.password, ConfigParam.MQTT_Param.mqtt_param_data.wifi_password, sizeof(wifi_config.sta.password));

    printf("initialise_wifi SSID:%s\n", wifi_config.sta.ssid);
    printf("initialise_wifi PASSWORD:%s\n", wifi_config.sta.password);
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); //这里可以写一些WIFI的配置

    //当wifi处于连接状态时,就开启wifi连接
    current_wifi_state = WIFI_DISABLE;
    wifi_turnon();
}

/**
 *  @brief wifi开启
 *  @param 无
 *  @brief 无  
 */
void wifi_turnon(void)
{
    if (current_wifi_state == WIFI_DISABLE)
    { //当wifi已经关闭时,才会从新开启wifi
        printf("Hello wifi_activate\n\r");
        ESP_ERROR_CHECK(esp_wifi_start());
    }
}

/**
 *  @brief wifi关闭
 *  @param 无
 *  @brief 无  
 */
void wifi_turnoff(void)
{
    if (current_wifi_state != WIFI_DISABLE)
    {                                        //如果wifi不处于WIFI_DISABLE状态,就关闭wifi
        current_wifi_state = WIFI_DISABLE;   //wifi关闭
        mqtt_is_connected = MQTT_DISCONNECT; //mqtt将要断开
        if (mqtt_is_create == MQTT_IS_CREATED)
        {                                         //mqtt被创建后,才会被destroy
            esp_mqtt_client_destroy(mqtt_client); //重连超过指定的次数后,将MQTT销毁
            mqtt_is_create = MQTT_NO_CREATED;     //mqtt被销毁了
        }
        wifi_destroy();
    }
    sntp_stop();
}

/**
 *  @brief 配置wifi进入配网模式
 *  @param 无
 *  @brief 无  
 */
void wifi_smartconfig(void)
{
    if (current_wifi_state != WIFI_SMARTCONFIG)
    { //当前不处于smartconfig模式时才进入smartconfig模式
        wifi_turnoff();
        ConfigParam.MQTT_Param.mqtt_param_data.wifi_mode = WIFI_SCANNING;
        write_config_param(&ConfigParam.MQTT_Param.mqtt_param_data.wifi_ssid, ConfigParam.MQTT_Param.pC, ConfigParam.MQTT_Param.length);
        current_wifi_state = WIFI_DISABLE;
        wifi_turnon();
    }
}
//上面是WIFI连接部分
/*********************************************************************************************************************/
